/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pgacoordinator;

import java.util.ArrayList;
import java.util.BitSet;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.baatar.opt.genetic.AlgorithmParameters;
import org.baatar.opt.genetic.selection.BinaryTournamentSelection;
import org.baatar.opt.genetic.set.covering.binary.SCChromosomeFactory;
import org.baatar.opt.genetic.set.covering.binary.SCCrossover;
import org.baatar.opt.genetic.set.covering.binary.SCImprover;
import org.baatar.opt.genetic.set.covering.binary.SCMutator;
import org.baatar.opt.genetic.set.meta.DataSet;
import org.baatar.opt.pga.impl.client.PGAClusterConnection;
import org.baatar.opt.pga.impl.service.Cluster;
import org.baatar.opt.pga.impl.service.PGACoordinatorServiceImpl;
import org.baatar.remoting.service.RemotingService;
import org.baatar.remoting.service.RemotingServiceInfo;
import org.baatar.util.XMLUtil;

/**
 *
 * @author Ba
 */
public class SCPGACoordinator {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        /**
         *      READ PAIR QUALITY (RATIO)
         */
        String inputXmlFileName = XMLUtil.readProperty("pgacoordinator.xml", "pgaCoordinator", "inputFile");
        String outputXmlFileName = XMLUtil.readProperty("pgacoordinator.xml", "pgaCoordinator", "outputFile");

//        org.baatar.opt.genetic.set.util.XMLUtil.convertPairXMLtoSetXML(inputXmlFileName, outputXmlFileName);
        DataSet dataSet = org.baatar.opt.genetic.set.util.XMLUtil.readSetOptimizationInputDataFromXML(inputXmlFileName);

        /**
         * Read coordinator info from configuration file.
         */
        String portNrStr = XMLUtil.readProperty("pgacoordinator.xml", "pgaCoordinator", "portNr");
        int portNr = Integer.valueOf(portNrStr);

        /**
         * Create implementation class and remoting service class.
         */
        PGACoordinatorServiceImpl<Boolean, BitSet> pgaCoordSrvImpl = new PGACoordinatorServiceImpl<Boolean, BitSet>();
        RemotingService pgaCoordinatorService = new RemotingService(pgaCoordSrvImpl, portNr);

        if (pgaCoordinatorService.initializeService()) {

            /**
             * Assign Logger.
             */
            Logger logger = Logger.getLogger(pgaCoordinatorService.getRemotingServiceInfo().toString());
            pgaCoordinatorService.setLogger(logger);
            logger.addAppender(new ConsoleAppender(new PatternLayout()));

            /**
             * Set algorithm preferences.
             */
            AlgorithmParameters<Boolean, BitSet> algoParams = new AlgorithmParameters<Boolean, BitSet>();

            algoParams.setMaxNumOfIterations(10000);
            algoParams.setMaxNumOfIterationsWOProgress(10000);
            algoParams.setPopulationSize(100);
            algoParams.setMinNumOfChildren(20);
            algoParams.setNumOfEliteChromosomes(4);
            algoParams.setMutationRate((float) (dataSet.rows.length / (2.0 * dataSet.columns.length)));
            algoParams.setGreedRate(0.0f);
            algoParams.setAllowDublicateChromosomes(false);

//            algoParams.setMigrationFrequency(100);

            algoParams.setChromosomeFactory(new SCChromosomeFactory(dataSet));
            algoParams.setSelector(new BinaryTournamentSelection<Boolean, BitSet>());
            algoParams.setCrossoverOperator(new SCCrossover());
            algoParams.setMutator(new SCMutator(dataSet.columns.length,
                                            dataSet.columns.length / 90.0,
                                            250,
                                            0.8));
            algoParams.setImprover(new SCImprover(dataSet));

            pgaCoordSrvImpl.setAlgoParams(algoParams);

            /**
             * Start coordinator service.
             */
            if (pgaCoordinatorService.startService()) {

                /**
                 * Register clusters defined in the configuration file.
                 */
                ArrayList<String> clusterHosts = XMLUtil.readProperties("pgacoordinator.xml", "pgaCluster", "host");
                ArrayList<String> clusterPorts = XMLUtil.readProperties("pgacoordinator.xml", "pgaCluster", "portNr");

                for (int i = 0; i < clusterHosts.size(); i++) {
                    PGAClusterConnection<Boolean, BitSet> clusterConnection = new PGAClusterConnection<Boolean, BitSet>();
                    clusterConnection.setHostName(clusterHosts.get(i));
                    clusterConnection.setPortNo(Integer.valueOf(clusterPorts.get(i)));
                    clusterConnection.setCallerInfo(pgaCoordinatorService.getRemotingServiceInfo().toString());

//                    int numOfWorkers = clusterConnection.registerCoordinator(pgaCoordinatorService.getRemotingServiceInfo(), i, algoParams);
//
//                    if (numOfWorkers > 0) {
//                        RemotingServiceInfo clusterNetInfo = clusterConnection.getClusterNetInfo();
//                        pgaCoordSrvImpl.addCluster(new Cluster<Boolean, BitSet>(pgaCoordinatorService.getRemotingServiceInfo(),
//                                                                                clusterNetInfo,
//                                                                                i,
//                                                                                numOfWorkers));
//                        pgaCoordinatorService.getLogger().info(clusterNetInfo + " is registered.");
//                    }
                }

                pgaCoordinatorService.getLogger().info("Ready.");
                pgaCoordSrvImpl.prepareOptimizers();
                pgaCoordSrvImpl.runOptimizers();
            }
        }
    }
}
